﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net.Sockets;

public interface IPayCtrl
{
    PayType payType { get; }
    bool initialized { get; }
    void InitIAP(Action onEnd);
    void CheckDropOrder();
    void Pay(GoodsArche goods, Action<string> onPayFail, Action<string, PaymentValidateResponseData> onValidateSuccess);
}

#if IAP
public class UnityPayCtrl : IPayCtrl
{
    private Action<string> m_PayFail;
    private Action<string, Response_PaymentValidate> m_OnValidateSuccess;

    private bool m_HasInit;
    public bool initialized => m_HasInit;
    
    private PayType m_PayType;

    public PayType payType => m_PayType;

    private UnityIAPController m_UnityIap;
    public UnityIAPController unityIAP
    {
        get
        {
            if (m_UnityIap == null)
            {
                UnityEngine.GameObject go = new UnityEngine.GameObject("UnityIAPController");
                m_UnityIap = go.AddComponent<UnityIAPController>();
            }

            return m_UnityIap;
        }
    }
    
    bool isShowLog
    {
        get
        {
            return true;
            //if (MGame.instance.config != null)
            //    return MGame.instance.config.ShowIAPLog;
            //else
            //    return false;
        }
    }

    public UnityPayCtrl()
    {
        m_PayType = UnityIAPController.GetPayType();
    }
    
    /// <summary>
    /// 初始化iap
    /// </summary>
    public void InitIAP(Action onEnd)
    {
        unityIAP.Init(m_PayType,() =>
        {
            m_HasInit = true;
            
            onEnd?.Invoke();
        });
    }

    /// <summary>
    /// 检查支付恢复和漏单
    /// </summary>
    public  void CheckDropOrder()
    {
        unityIAP.CheckDropOrder();
    }

 

    public void Pay(GoodsArche goods, Action<string> onPayFail,  Action<string, Response_PaymentValidate> onValidateSuccess)
    {
        m_PayFail = onPayFail;
        m_OnValidateSuccess = onValidateSuccess;
            
        ShowMask();
        
        IAPParam iapParam = new IAPParam(goods.goodsId,GetProductID(goods,m_PayType));
        
        GameDebug.LogError($"goods:{goods.goodsId}   payType:{m_PayType}  pid:{iapParam.productPid}");
        try
        {
            unityIAP.Purchase(iapParam, OnPayFail, OnPaySuc);
        }
        catch (Exception e)
        {
            GameDebug.LogError(e);
            onPayFail?.Invoke(e.Message);
        }
    }

    void OnPayFail(string failReason)
    {
        HideMask();
        
        m_PayFail?.Invoke(failReason);
    }

    void OnPaySuc(PaymentData paymentData)
    {   
        m_TryCount = 0;

        DoActionDelay.DelayAction(1,(() =>
        {
            SendRequset_PaymentSuccessValidate(paymentData.goodsId, paymentData.productPid,paymentData.payType, paymentData.transaction,
                paymentData.receipt);
        }));
    }
    

    public static string GetProductID(GoodsArche goods, PayType payType)
    {
        if (payType == PayType.IOS)
        {
            return goods.applePurchaseId;
        }
        else if (payType == PayType.Google)
        {
            return goods.googlePurchaseId;
        }
        else if (payType == PayType.UDP)
        {
            return goods.unityPurchaseId;
        } 
        else if (payType == PayType.EDITOR)
        {
            return goods.unityPurchaseId;
        }
        else
        {
            GameDebug.Log($"未支持支付类型：{payType}");
            return goods.goodsId;
        }
    }


    private int timeOutCount = 10;
    private PaymentValidateData m_CurValidateData;
    private int m_TryCount;
    /// <summary>
    /// 支付成功后发起成功的验证请求
    /// </summary>
    void SendRequset_PaymentSuccessValidate(string goodsId,string productId,int payType,string transaction, string receipt)
    {
        Request_PaymentValidate req = new Request_PaymentValidate();
        req.clientSocket = MGame.instance.clientSocket;
        
        req.validateData = new PaymentValidateData();
        req.validateData.goodsId = goodsId;
        req.validateData.productId = productId;
        req.validateData.payType = payType;
        req.validateData.transactionId = transaction;
        req.validateData.receipt = receipt;

        if (m_PayType == PayType.Google)
        {
            string tempReceipt = DecodePurchaseTokenGoogle(receipt);
            if (string.IsNullOrEmpty(tempReceipt))
            {
                GameDebug.LogError("SendRequset_PaymentSuccessValidate,DecodePurchaseTokenGoogle fail");
                return;
            }
            req.validateData.receipt  = tempReceipt;
        }

        req.onTimeOut = (request)=>
        {
            if (m_CurValidateData != null && m_TryCount < timeOutCount)
            {
                m_TryCount++;
                SendRequset_PaymentSuccessValidate(m_CurValidateData.goodsId, m_CurValidateData.productId,
                    m_CurValidateData.payType, m_CurValidateData.transactionId, m_CurValidateData.receipt);
            }
            else
            {
                ValidateRequest_OutTime(request as Request_PaymentValidate);
            }
        };
        req.onResponse =(res)=>
        {
            m_TryCount = 0;
            ValidateRequest_Response(res as Response_PaymentValidate);
        };
        
#if UNITY_EDITOR
        if(m_TryCount == 0)
            (MGame.instance.clientSocket as TCPSocket).StopConnect();
#endif

        m_CurValidateData = req.validateData;
        req.Send();
        
        GameDebug.LogShowy($"NetRequest_PaymentValidate  payType:{payType}");
    }
    
    /// <summary>
    /// 验证超时
    /// </summary>
    /// <param name="req"></param>
    void ValidateRequest_OutTime(Request_PaymentValidate req)
    {
        string message = isShowLog ? Localization.instance.GetValue("pay_verify_timeout") + "_1" : Localization.instance.GetValue("pay_verify_timeout");
        ShowNotice(message);
    }
    /// <summary>
    /// 验证回调
    /// </summary>
    /// <param name="res"></param>
    void ValidateRequest_Response(Response_PaymentValidate res)
    {
        string message = "";

        try
        {
            PaymentValidateResponseData response = res.responseData as PaymentValidateResponseData;
            
            if (res == null)
            {
                message = isShowLog ? Localization.instance.GetValue("pay_verify_fail") + "_0" : Localization.instance.GetValue("pay_verify_fail");
                MGame.instance.ShowNoticePanel(message);
                return;
            }

            long paymentId = response.paymentId;
            string internalPid = response.internalPid;
            string goodsId = response.goodsId;

            GameDebug.LogShowy($"ValidateRequest_Response code:{response.code}  goodsId:{goodsId}");

            if (response.code == ResponseCode_PaymentPaySuccess.success)
            {
                if (m_PayFail == null)//漏单处理的验证
                {
                    MGame.instance.ShowNoticePanel(Localization.instance.GetValue("pay_restore_success"));
                }
                else//正常购买的验证
                {
                    /*if(m_PaySuccess != null)
                        m_PaySuccess(Localization.instance.GetValue("pay_success"));*/
                }

                //验证成功回调
                m_OnValidateSuccess?.Invoke(goodsId, res);

            }
            else if (response.code == ResponseCode_PaymentPaySuccess.verifyReceiptFail)
            {
                message = isShowLog ? Localization.instance.GetValue("pay_verify_fail") + "_2" : Localization.instance.GetValue("pay_verify_fail");
                ShowNotice(message);
            }
            else if (response.code == ResponseCode_PaymentPaySuccess.verifyReceiptTimeout)
            {
                message = isShowLog ? Localization.instance.GetValue("pay_verify_timeout") + "_2" : Localization.instance.GetValue("pay_verify_timeout");
                ShowNotice(message);
            }
            else if (response.code == -1)
            {
                ShowNotice(response.err);
            }
            else
            {
                ShowNotice(response.err);
            }
        }
        catch (Exception e)
        {
            GameDebug.LogError("ValidateRequest_Response,error：" + e);
            message = isShowLog ? Localization.instance.GetValue("pay_verify_fail") + "_3" : Localization.instance.GetValue("pay_verify_fail");
            ShowNotice(message);
        }
        finally
        {
            HideMask();
        }
    }
    
    string DecodePurchaseTokenGoogle(string receipt)
    {
        try
        {
            GameDebug.LogShowy("start DecodePurchaseTokenGoogle");
            Dictionary<string, object> json = MiniJSON.Json.Deserialize(receipt) as Dictionary<string, object>;
            receipt = (string)json["json"];
            GameDebug.Log(receipt);
            json = MiniJSON.Json.Deserialize(receipt) as Dictionary<string, object>;
            GameDebug.LogShowy($"end DecodePurchaseTokenGoogle,{(string)json["purchaseToken"]}");

            return (string)json["purchaseToken"];
        }
        catch (System.Exception e)
        {
            GameDebug.LogError($"DecodePurchaseTokenGoogle error:{e}");
            MGame.instance.ShowNoticePanel($"DecodePurchaseTokenGoogle error");
            return "";
        }
    }

    void ShowNotice(string content)
    {
        HideMask();
        MGame.instance.ShowNoticePanel(content);
    }
    
    /// <summary>
    /// 显示遮罩
    /// </summary>
    void ShowMask()
    {
        PanelLoading.Show(60);
    }

    /// <summary>
    /// 隐藏遮罩
    /// </summary>
    void HideMask()
    {
        PanelLoading.Hide();
    }

}

#endif